#include <mutex>
#include <condition_variable>
#include <thread>
#include <cstddef>
#include <memory>
#include <exception>
#include "simple_barrier.h"

class SimpleBarrierImpl {
public:
    SimpleBarrierImpl(size_t count) : count_(count), waiting_(0) {}

    void wait() {
        std::unique_lock<std::mutex> lock(mutex_);
        ++waiting_;
        if (waiting_ == count_) {
            waiting_ = 0;
            cv_.notify_all();
        } else {
            cv_.wait(lock, [this] { return waiting_ == 0; });
        }
    }

private:
    std::mutex mutex_;
    std::condition_variable cv_;
    size_t count_;
    size_t waiting_;
};

SimpleBarrier::SimpleBarrier(size_t count)
{
    impl_ = new SimpleBarrierImpl(count);
    if (!impl_) {
        throw std::bad_alloc();
    }
}

SimpleBarrier::~SimpleBarrier()
{
    if (impl_) {
        delete impl_;
    }
}

void SimpleBarrier::wait()
{
    impl_->wait();
}

